package com.sangsang.kafka.util;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.sangsang.kafka.exceptions.CdcException;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author liutangqi
 * @date 2023/12/25 9:14
 */
public class CDCUtils {

    /**
     * 判断两个对象中 没有@TableField(exist = false) 的字段的值是否相等
     *
     * @author liutangqi
     * @date 2023/12/25 9:15
     * @Param [obg1, obj2]
     **/
    public static boolean equal(Object obj1, Object obj2) {
        if (obj1 == obj2) {
            return true;
        }
        if (obj1 == null || obj2 == null || obj1.getClass() != obj2.getClass()) {
            return false;
        }

        //过滤出当前类没有没有@TableField(exist = false) 的字段
        List<Field> needCompareFields = ReflectUtils.getAllFields(obj1.getClass())
                .stream()
                .filter(f -> f.getAnnotation(TableField.class) == null || f.getAnnotation(TableField.class).exist())
                .collect(Collectors.toList());

        //逐个比较每个字段的值
        long notEqualCount = needCompareFields.stream()
                .map(Field::getName)
                .filter(f -> !Objects.equals(ReflectUtils.getFieldValue(obj1, f), ReflectUtils.getFieldValue(obj2, f)))
                .count();

        return notEqualCount == 0;
    }

    /**
     * 获取当前对象的主键值
     * 优先获取@TableId 标注的字段
     * 找不到的话，找字段名叫“id”的字段的值
     *
     * @author liutangqi
     * @date 2023/12/25 15:11
     * @Param []
     **/
    public static Object getPrimaryKeyValue(Object obj) {
        //获取所有字段
        List<Field> allFields = ReflectUtils.getAllFields(obj.getClass());

        //优先获取标注了@TableId的字段，找不到的话，找叫“id”的字段
        Field field = allFields.stream()
                .filter(f -> f.getAnnotation(TableId.class) != null)
                .findAny()
                .orElse(allFields.stream().filter(f -> "id".equals(f.getName())).findAny().orElseThrow(() -> new CdcException("请标注主键字段")));

        //获取这个字段的值
        field.setAccessible(true);
        Object result = null;
        try {
            result = field.get(obj);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        Optional.ofNullable(result).orElseThrow(() -> new CdcException("主键值为空，无法处理"));
        return result;
    }
}
